//Copyright (c) 2007 Andrew Badera andrew@badera.us
//SVN repository at http://powncenet.googlecode.com/svn/

//Permission is hereby granted, free of charge, to any person
//obtaining a copy of this software and associated documentation
//files (the "Software"), to deal in the Software without
//restriction, including without limitation the rights to use,
//copy, modify, merge, publish, distribute, sublicense, and/or sell
//copies of the Software, and to permit persons to whom the
//Software is furnished to do so, subject to the following
//conditions:

//The above copyright notice and this permission notice shall be
//included in all copies or substantial portions of the Software.

//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
//EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
//OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
//NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
//HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
//WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
//FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
//OTHER DEALINGS IN THE SOFTWARE.


using System;
using System.Collections.Generic;
using System.Globalization;
using System.Text;
using System.Xml;

using BadException;
using BadWeb;
using BadUtil;

namespace PownceNET
{
    /// <summary>
    /// Instance class of Pownce user Session.
    /// Used to authenticate user, persist session data.
    /// </summary>
    public static class Session
    {
        private static string _token = string.Empty;

        /// <summary>
        /// Gets or sets the Pownce API token.
        /// </summary>
        /// <value>The token.</value>
        public static string Token
        {
            get { return Session._token; }
            set { Session._token = value; }
        }

        private static string _sessionID = string.Empty;

        /// <summary>
        /// Gets or sets the session ID.
        /// </summary>
        /// <value>The session ID.</value>
        public static string SessionID
        {
            get { return Session._sessionID; }
            set { Session._sessionID = value; }
        }

        private static string _lastResponseCode = string.Empty;

        /// <summary>
        /// Gets or sets the last HTTP response code.
        /// </summary>
        /// <value>The response code.</value>
        public static string LastResponseCode
        {
            get { return Session._lastResponseCode; }
            set { Session._lastResponseCode = value; }
        }

        /// <summary>
        /// Logs in the specified user, gets the API token.
        /// </summary>
        /// <param name="username">The username.</param>
        /// <param name="password">The password.</param>
        public static void Login(string username, string password)
        {
            if (string.IsNullOrEmpty(username))
            {
                throw new ArgumentException("Requires username.");
            }

            if (string.IsNullOrEmpty(password))
            {
                throw new ArgumentException("Requires password.");
            }

            string response = string.Empty;

            //try to login
            try
            {
                response = Get.DoGet(UrlConstants.LOGIN, HttpConstants.X_WWW_URLENCODED, username, password);
            }
            catch (Exception ex)
            {
                //whoops, something went wrong. log it.
                BadLogger.WriteToLog("Session.Login", ex, ExceptionEnums.LogEntryType.Error);
                throw ex;
            }

            XmlDocument xml = new XmlDocument();

            //try to parse the response as XML
            try
            {
                xml.LoadXml(response);
            }
            catch (Exception ex)
            {
                //whoops something went wrong. log it.
                BadLogger.WriteToLog("Session.Login", string.Format("Could not load XML response:{0}{1}.", Environment.NewLine, response), ExceptionEnums.LogEntryType.Error);
                throw new XmlException("Could not load XML response.", ex);
            }
            
            //get the login node
            XmlNode login = xml.GetElementsByTagName("login")[0];
            
            //get the API token
            _token = login.Attributes["token"].Value;

            xml = null;
        }

        /// <summary>
        /// Gets a Pownce WSSE digest.
        /// Uses the Amazon standard of a service-emitted token
        /// rather than user password as the secret value.
        /// </summary>
        /// <returns></returns>
        public static string GetPownceWSSEDigest(ref string shortnonce, ref string timestamp)
        {
            if (string.IsNullOrEmpty(Session._token))
            {
                Session.Login(User.USERNAME, User.PASSWORD);
            }

            //get datetime for use in current transaction
            //in universal time for latter
            DateTime now = DateTime.Now.ToUniversalTime();

            //get nonce value for WSSE token and digest
            shortnonce = WSSE.GetNonce();

            //get created timestamp for WSSE token and digest
            //YYYY-MM-DDTHH:MM:SSZ
            timestamp = now.ToUniversalTime().ToString(DateTimeFormatInfo.InvariantInfo.SortableDateTimePattern) + "Z";

            //get digest for WSSE token
            string digest = WSSE.ComputePasswordDigest(shortnonce, timestamp, Session._token);

            return digest;
        }
    }
}
